package tech.lingrui.mnpanonymousservice.websocket;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import tech.lingrui.mnpanonymousservice.model.*;
import tech.lingrui.mnpanonymousservice.service.GameService;
import tech.lingrui.mnpanonymousservice.service.impl.GameServiceImpl;
import tech.lingrui.mnpanonymousservice.util.JsonUtils;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * game sw
 *
 * @author lqs2
 * @date 2018/11/25, Sun
 */
@Component
@ServerEndpoint(value = "/ws/{username}")
@Slf4j
public class GameWebSocket {

    /**
     * 在线人数
     */
    private static int onlineNumber = 0;

    /**
     * 所有的连接对象 <username, ws模型>
     */

    private static Map<UserModel, GameWebSocket> clients = new ConcurrentHashMap<>();


    /**
     * json
     */
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();


    /**
     * 游戏服务操作
     */
    private final GameService gameService = new GameServiceImpl();
    /**
     * 用户名
     */
    private UserModel user;

    /**
     * 会话
     */
    private Session session;

//    @Autowired
//    public GameWebSocket(GameService gameService) {
//        this.gameService = gameService;
//    }

    /**
     * 建立连接
     *
     * @param session 会话
     */
    @OnOpen
    public String onOpen(@PathParam("username") String username, Session session) {
        UserModel user = new UserModel(username, UserModel.USER_STATE_FREE);
        clients.put(user, this);
        this.session = session;
        this.user = user;
        addMember();
        log.info("用户名【{}】加入，当前在线人数：{}", username, onlineNumber);
        return "helloworld";
    }

    /**
     * 连接关闭
     */
    @OnClose
    public void onClose() {
        clients.remove(user);
        subMember();
        log.info("用户名【{}】离开了，当前在线人数：{}", user.getName(), onlineNumber);
    }

    /**
     * 收到客户端的消息
     *
     * @param jsonStr 消息
     * @param session 会话
     */
    @OnMessage
    public void onMessage(String jsonStr, Session session) {
        log.info("收到消息 -> {}", jsonStr);
        GameMessage gMsg;
        ResponseMessage rMsg;
        String gameId;
        try {
            RequestMessage msg = OBJECT_MAPPER.readValue(jsonStr, RequestMessage.class);
            int type = msg.getGameMessage().getType();
            switch (type) {
                case GameMessage.CREATE_GAME:
                    GameModel gameModel = gameService.createGame(user);
                    log.info("{}", gameModel);
                    sendMessageToUser(user.getName(), "创建成功，游戏编号：【 " + gameModel.getId() + " 】");
                    sendMessageAll(user.getName(), "我创建了一局游戏，编号：【" + gameModel.getId() + "】快来加入吧");
                    return;
                case GameMessage.JOIN_GAME_RANDOM:
                    gameService.randomMatch(user);
                    return;

                case GameMessage.START_GAME:
                    gameId = msg.getContent();
                    gameService.startGame(gameId);

                    rMsg = new ResponseMessage();
                    rMsg.setType(BaseMessage.MSY_TYPE_GAME);
                    gMsg = new GameMessage();
                    gMsg.setType(GameMessage.ANSWER_QUESTION);
                    gMsg.setRoundNo(0);
                    rMsg.setData(gMsg);



                    sendMessageToUser(user.getName(), rMsg);
                    return;

                case GameMessage.ANSWER_QUESTION:

                    return;

                case GameMessage.JOIN_GAME_SHARE:
                     gameId = msg.getContent();
                    GameModel model = gameService.getGameInfo(gameId);
                    if (model != null) {
//                        UserModel participate = new UserModel(username);
                        boolean success = gameService.joinGame(gameId, user);
                        if (success) {
                            sendMessageToUser(user.getName(), "加入成功，游戏编号：【 " + model.getId() + " 】，等待游戏开始");
                            sendMessageToUser(model.getCreator().getName(), "我加入了你的游戏，游戏编号：【 " + model.getId() + " 】，等待游戏开始");
                            sendMessageAll(model.getCreator().getName(), "游戏编号：【" + model.getId() + "】已经开局，禁止加入");
                            if (model.getState() == GameModel.STATE_WAITING_START) {
                                gameService.startGame(gameId);

                                ResponseMessage rsp = new ResponseMessage();
                                GameMessage gmsg = new GameMessage();
                                gmsg.setType(GameMessage.START_GAME);

                                rsp.setDestUser(user.getName());
                                rsp.setGameMessage(gmsg);
                                rsp.setData(model);
                                rsp.setType(BaseMessage.MSY_TYPE_GAME);

                                // 通知用户可以开始游戏
                                sendMessageToUsers("游戏编号：【 " + model.getId() + " 】，已经开始", user.getName(), model.getCreator().getName());
                                // 发送题目给客户端
                                sendMessageToUsers(rsp, user.getName(), model.getCreator().getName());
                            }
                        } else {
                            if (model.getState() == GameModel.STATE_TIME_OUT) {
                                sendMessageToUser(user.getName(), "加入失败，游戏编号：【 " + model.getId() + " 】已经失效");
                            }
                        }
                    }
                    return;
                case GameMessage.FINISH_GAME:
                    return;
                default:
                    sendMessageToUser(user.getName(), "非法操作");
                    break;
            }
        } catch (Exception e) {
            log.error("", e);
        }
    }


    public void sendMessageToUsers(ResponseMessage msg, String... names) throws IOException {
        for (String name : names) {
            sendMessageToUser(name, msg);
        }
    }

    public void sendMessageToUsers(String msg, String... names) throws IOException {
        for (String name : names) {
            sendMessageToUser(name, msg);
        }
    }


    public void sendMessageToUser(String destUsername, ResponseMessage message) throws IOException {
        if (user.getName().equals(destUsername)) {
            session.getAsyncRemote().sendText(JsonUtils.convertToJsonStr(message));
            return;
        }
        for (GameWebSocket item : clients.values()) {
            if (item.user.getName().equals(destUsername)) {
                item.session.getAsyncRemote().sendText(JsonUtils.convertToJsonStr(message));
                return;
            }
        }
    }

    private void sendMessageToUser(String destUsername, String message) throws IOException {
        ResponseMessage msg = new ResponseMessage();
        msg.setType(BaseMessage.MSY_TYPE_TO_ONE);
        msg.setDestUser(destUsername);
        if (user.getName().equals(destUsername)) {
            msg.setContent(message);
            session.getAsyncRemote().sendText(JsonUtils.convertToJsonStr(msg));
            return;
        }
        for (GameWebSocket item : clients.values()) {
            if (item.user.getName().equals(destUsername)) {
                msg.setContent("来自用户【 " + user.getName() + " 】的消息：" + message);
                item.session.getAsyncRemote().sendText(JsonUtils.convertToJsonStr(msg));
                return;
            }
        }
    }


    private void sendMessageAll(String sourceUser, String message) throws IOException {
        ResponseMessage msg = new ResponseMessage();
        msg.setContent("来自【" + sourceUser + "】的消息: " + message);
        msg.setSourceUser(sourceUser);
        msg.setType(BaseMessage.MSY_TYPE_TO_ALL);
        clients.values()
                .forEach(v -> {
                    try {
                        v.session.getAsyncRemote().sendText(JsonUtils.convertToJsonStr(msg));
                    } catch (JsonProcessingException e) {
                        log.error("", e);
                    }
                });
    }


//    /**
//     * 发送消息
//     *
//     * @param message 消息
//     */
//    public void sendMessage(String message) {
//        try {
//            session.getBasicRemote().sendText(message);
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//    }

    public static Map<UserModel, GameWebSocket> getClients() {
        return clients;
    }


    private static synchronized void subMember() {
        onlineNumber--;
    }

    private static synchronized void addMember() {
        onlineNumber++;
    }


}
